package yunjiao.designpatterns.builder;

/**
 * TODO
 *
 * @author yangyunjiao
 */
public class GenericBuilder<T> {
    private final T instance;
    private boolean built = false;

    private GenericBuilder(T instance) {
        this.instance = instance;
    }

    public static <T> GenericBuilder<T> of(Class<T> clazz) {
        try {
            return new GenericBuilder<>(clazz.getDeclaredConstructor().newInstance());
        } catch (Exception e) {
            throw new RuntimeException("Failed to create instance", e);
        }
    }

    public <V> GenericBuilder<T> with(Setter<T, V> setter, V value) {
        if (built) {
            throw new IllegalStateException("Builder has already been used");
        }
        setter.set(instance, value);
        return this;
    }

    public T build() {
        built = true;
        return instance;
    }

    @FunctionalInterface
    public interface Setter<T, V> {
        void set(T target, V value);
    }
}
